package org.zxw.utils;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * JWT 工具类
 * 需要自行配置的内容：
 * 1. application.yml 中的 jwt 配置项
 * 2. 根据项目需求调整 token 有效时间
 * 3. 自定义 claims 内容
 */
@Component
@Data
public class JwtUtil {

    // ==================== 需要配置的内容 START ====================
    // 以下值应从 application.yml 配置文件中读取

    /**
     * JWT 加密密钥(Base64编码格式)
     * 需要在 application.yml 中配置：
     * jwt:
     *   secret: your-secret-key-base64-encoded
     */
    @Value("${jwt.secret}")
    private String secret;

    /**
     * JWT 过期时间(毫秒)
     * 默认 7 天，根据项目需求调整
     * 需要在 application.yml 中配置：
     * jwt:
     *   expiration: 604800000
     */
    @Value("${jwt.expiration}")
    private Long expiration;

    private String Token = "token";

    // ==================== 需要配置的内容 END ====================

    /**
     * 生成加密密钥
     */
    private SecretKey getSigningKey() {
        // 将 Base64 编码的密钥转换为 SecretKey
        return Keys.hmacShaKeyFor(java.util.Base64.getDecoder().decode(secret));
    }

    /**
     * 生成 JWT token
     * @param claims 自定义 claims 内容
     * @param subject 主题(通常是用户ID或用户名)
     * @return JWT token
     */
    public String generateToken(Map<String, Object> claims, String subject) {
        return Jwts.builder()
                .setClaims(claims)                      // 自定义 claims
                .setSubject(subject)                   // 主题
                .setIssuedAt(new Date())              // 签发时间
                .setExpiration(new Date(System.currentTimeMillis() + expiration)) // 过期时间
                .signWith(getSigningKey(), SignatureAlgorithm.HS256) // 签名算法和密钥
                .compact();
    }

    /**
     * 从 token 中获取 claims
     * @param token JWT token
     * @return claims
     */
    public Claims getClaimsFromToken(String token) {
        JwtParser parser = Jwts.parser()
                .verifyWith(getSigningKey())
                .build();
        return parser.parseSignedClaims(token).getPayload();
    }

    /**
     * 从 token 中获取主题(通常是用户ID)
     * @param token JWT token
     * @return 主题
     */
    public String getSubjectFromToken(String token) {
        return getClaimsFromToken(token).getSubject();
    }

    /**
     * 获取 token 的过期时间
     * @param token JWT token
     * @return 过期时间
     */
    public Date getExpirationDateFromToken(String token) {
        return getClaimsFromToken(token).getExpiration();
    }

    /**
     * 验证 token 是否过期
     * @param token JWT token
     * @return 是否过期
     */
    public Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }

    /**
     * 生成 token (简化版，使用默认 claims)
     * @param subject 主题(通常是用户ID)
     * @return JWT token
     */
    public String generateToken(String subject) {
        Map<String, Object> claims = new HashMap<>();
        // 可以在这里添加默认 claims
        return generateToken(claims, subject);
    }


    /**
     * 验证 token 是否有效
     * @param token JWT token
     * @param subject 主题(通常是用户ID)
     * @return 是否有效
     */
    public Boolean validateToken(String token, String subject) {
        final String tokenSubject = getSubjectFromToken(token);
        return (tokenSubject.equals(subject) && !isTokenExpired(token));
    }
}
